home *** CD-ROM | disk | FTP | other *** search
- #ifndef lint, place, &x, &y)Sid = "$Id: graph3d.c,v 1.13.2.4 1999/10/19 13:31:49 lhecking Exp $";
- #endif
-
- /* GNUPLOT - graph3d.c */
-
- /*[
- * Copyright 1986 - 1993, 1998 Thomas Williams, Colin Kelley
- *
- * Permission to use, copy, and distribute this software and its
- * documentation for any purpose with or without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and
- * that both that copyright notice and this permission notice appear
- * in supporting documentation.
- *
- * Permission to modify the software is granted, but not the right to
- * distribute the complete modified source code. Modifications are to
- * be distributed as patches to the released version. Permission to
- * distribute binaries produced by compiling modified sources is granted,
- * provided you
- * 1. distribute the corresponding source modifications from the
- * released version in the form of a patch file along with the binaries,
- * 2. add special version identification to distinguish your version
- * in addition to the base release version number,
- * 3. provide your name and address as the primary contact for the
- * support of your modified version, and
- * 4. retain our contact information in regard to use of the base
- * software.
- * Permission to distribute the released version of the source code along
- * with corresponding source modifications in the form of a patch file is
- * granted with same provisions 2 through 4 for binary distributions.
- *
- * This software is provided "as is" without express or implied warranty
- * to the extent permitted by applicable law.
- ]*/
-
-
- /*
- * AUTHORS
- *
- * Original Software:
- * Gershon Elber and many others.
- *
- * 19 September 1992 Lawrence Crowl (crowl@cs.orst.edu)
- * Added user-specified bases for log scaling.
- *
- * 3.6 - split graph3d.c into graph3d.c (graph),
- * util3d.c (intersections, etc)
- * hidden3d.c (hidden-line removal code)
- *
- */
-
- #include "plot.h"
- #include "setshow.h"
-
- static int p_height;
- static int p_width; /* pointsize * t->h_tic */
- static int key_entry_height; /* bigger of t->v_size, pointsize*t->v_tick */
-
- int suppressMove = 0; /* to prevent moveto while drawing contours */
-
- /*
- * hidden_line_type_above, hidden_line_type_below - controls type of lines
- * for above and below parts of the surface.
- * hidden_no_update - if TRUE lines will be hidden line removed but they
- * are not assumed to be part of the surface (i.e. grid) and therefore
- * do not influence the hidings.
- * hidden_active - TRUE if hidden lines are to be removed.
- */
- int hidden_active = FALSE;
- int hidden_no_update; /* HBB 980324: made this visible despite LITE */
-
- /* LITE defines a restricted memory version for MS-DOS, which doesn't
- * use the routines in hidden3d.c
- */
-
- #ifndef LITE
- int hidden_line_type_above, hidden_line_type_below;
- #endif /* LITE */
-
-
- static double LogScale __PROTO((double coord, TBOOLEAN is_log,
- double log_base_log, char *what, char *axis));
- static void plot3d_impulses __PROTO((struct surface_points * plot));
- static void plot3d_lines __PROTO((struct surface_points * plot));
- static void plot3d_points __PROTO((struct surface_points * plot));
- static void plot3d_dots __PROTO((struct surface_points * plot));
- static void cntr3d_impulses __PROTO((struct gnuplot_contours * cntr,
- struct surface_points * plot));
- static void cntr3d_lines __PROTO((struct gnuplot_contours * cntr));
- static void cntr3d_points __PROTO((struct gnuplot_contours * cntr,
- struct surface_points * plot));
- static void cntr3d_dots __PROTO((struct gnuplot_contours * cntr));
- static void check_corner_height __PROTO((struct coordinate GPHUGE * point,
- double height[2][2], double depth[2][2]));
- static void draw_bottom_grid __PROTO((struct surface_points * plot,
- int plot_count));
- static void xtick_callback __PROTO((int axis, double place, char *text,
- struct lp_style_type grid));
- static void ytick_callback __PROTO((int axis, double place, char *text,
- struct lp_style_type grid));
- static void ztick_callback __PROTO((int axis, double place, char *text,
- struct lp_style_type grid));
- static void setlinestyle __PROTO((struct lp_style_type style));
-
- static void boundary3d __PROTO((int scaling, struct surface_points * plots,
- int count));
- #if 0 /* not used */
- static double dbl_raise __PROTO((double x, int y));
- #endif
- static void map_position __PROTO((struct position * pos, unsigned int *x,
- unsigned int *y, char *what));
-
- /* put entries in the key */
- static void key_sample_line __PROTO((int xl, int yl));
- static void key_sample_point __PROTO((int xl, int yl, int pointtype));
- static void key_text __PROTO((int xl, int yl, char *text));
-
-
- #if defined(sun386) || defined(AMIGA_SC_6_1)
- static double CheckLog __PROTO((TBOOLEAN is_log, double base_log, double x));
- #endif
-
- /*
- * The Amiga SAS/C 6.2 compiler moans about macro envocations causing
- * multiple calls to functions. I converted these macros to inline
- * functions coping with the problem without loosing speed.
- * (MGR, 1993)
- */
- #ifdef AMIGA_SC_6_1
- GP_INLINE static TBOOLEAN i_inrange(int z, int min, int max)
- {
- return ((min < max) ? ((z >= min) && (z <= max)) : ((z >= max) && (z <= min)));
- }
-
- GP_INLINE static double f_max(double a, double b)
- {
- return (max(a, b));
- }
-
- GP_INLINE static double f_min(double a, double b)
- {
- return (min(a, b));
- }
-
- #else
- # define f_max(a,b) GPMAX((a),(b))
- # define f_min(a,b) GPMIN((a),(b))
- # define i_inrange(z,a,b) inrange((z),(a),(b))
- #endif
-
- #define apx_eq(x,y) (fabs(x-y) < 0.001)
- #define ABS(x) ((x) >= 0 ? (x) : -(x))
- #define SQR(x) ((x) * (x))
-
- /* Define the boundary of the plot
- * These are computed at each call to do_plot, and are constant over
- * the period of one do_plot. They actually only change when the term
- * type changes and when the 'set size' factors change.
- */
-
- /* in order to allow graphic.c to use clip_draw_line, we must
- * share xleft, xright, ybot, ytop with graphics.c
- */
- extern int xleft, xright, ybot, ytop;
-
- int xmiddle, ymiddle, xscaler, yscaler;
- static int ptitl_cnt;
- static int max_ptitl_len;
- static int titlelin;
- static int key_sample_width, key_rows, key_cols, key_col_wth, yl_ref;
- static int ktitle_lines = 0;
-
-
- /* Boundary and scale factors, in user coordinates */
- /* x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d are local to this
- * file and are not the same as variables of the same names in other files
- */
- /*static double x_min3d, x_max3d, y_min3d, y_max3d, z_min3d, z_max3d; */
- /* sizes are now set in min_array[], max_array[] from plot.c */
- extern double min_array[], max_array[];
- extern int auto_array[], log_array[];
- extern double base_array[], log_base_array[];
-
- /* for convenience while converting to use these arrays */
- #define x_min3d min_array[FIRST_X_AXIS]
- #define x_max3d max_array[FIRST_X_AXIS]
- #define y_min3d min_array[FIRST_Y_AXIS]
- #define y_max3d max_array[FIRST_Y_AXIS]
- #define z_min3d min_array[FIRST_Z_AXIS]
- #define z_max3d max_array[FIRST_Z_AXIS]
-
- /* There are several z's to take into account - I hope I get these
- * right !
- *
- * ceiling_z is the highest z in use
- * floor_z is the lowest z in use
- * base_z is the z of the base
- * min3d_z is the lowest z of the graph area
- * max3d_z is the highest z of the graph area
- *
- * ceiling_z is either max3d_z or base_z, and similarly for floor_z
- * There should be no part of graph drawn outside
- * min3d_z:max3d_z - apart from arrows, perhaps
- */
-
- double ceiling_z, floor_z, base_z;
-
- /* and some bodges while making the change */
- #define min3d_z min_array[FIRST_Z_AXIS]
- #define max3d_z max_array[FIRST_Z_AXIS]
-
-
- double xscale3d, yscale3d, zscale3d;
-
-
- typedef double transform_matrix[4][4];
- transform_matrix trans_mat;
-
- static double xaxis_y, yaxis_x, zaxis_x, zaxis_y;
-
- /* the co-ordinates of the back corner */
- static double back_x, back_y;
-
- /* the penalty for convenience of using tic_gen to make callbacks
- * to tick routines is that we cant pass parameters very easily.
- * We communicate with the tick_callbacks using static variables
- */
-
- /* unit vector (terminal coords) */
- static double tic_unitx, tic_unity;
-
- /* (DFK) Watch for cancellation error near zero on axes labels */
- #define SIGNIF (0.01) /* less than one hundredth of a tic mark */
- #define CheckZero(x,tic) (fabs(x) < ((tic) * SIGNIF) ? 0.0 : (x))
- #define NearlyEqual(x,y,tic) (fabs((x)-(y)) < ((tic) * SIGNIF))
-
- /* And the functions to map from user to terminal coordinates */
- #define map_x(x) (int)(x+0.5) /* maps floating point x to screen */
- #define map_y(y) (int)(y+0.5) /* same for y */
-
- /* And the functions to map from user 3D space into normalized -1..1 */
- #define map_x3d(x) ((x-x_min3d)*xscale3d-1.0)
- #define map_y3d(y) ((y-y_min3d)*yscale3d-1.0)
- #define map_z3d(z) ((z-floor_z)*zscale3d-1.0)
-
-
-
- /* Initialize the line style using the current device and set hidden styles
- * to it as well if hidden line removal is enabled */
- static void setlinestyle(style)
- struct lp_style_type style;
- {
- term_apply_lp_properties(&style);
-
- #ifndef LITE
- if (hidden3d) {
- hidden_line_type_above = style.l_type;
- hidden_line_type_below = style.l_type;
- }
- #endif /* LITE */
- }
-
- /* (DFK) For some reason, the Sun386i compiler screws up with the CheckLog
- * macro, so I write it as a function on that machine.
- *
- * Amiga SAS/C 6.2 thinks it will do too much work calling functions in
- * macro arguments twice, thus I inline theese functions. (MGR, 1993)
- */
- #if defined(sun386) || defined(AMIGA_SC_6_1)
- GP_INLINE static double CheckLog(is_log, base_log, x)
- TBOOLEAN is_log;
- double base_log;
- double x;
- {
- if (is_log)
- return (pow(base_log, x));
- else
- return (x);
- }
- #else
- /* (DFK) Use 10^x if logscale is in effect, else x */
- # define CheckLog(is_log, base_log, x) ((is_log) ? pow(base_log, (x)) : (x))
- #endif /* sun386 || SAS/C */
-
- static double LogScale(coord, is_log, log_base_log, what, axis)
- double coord; /* the value */
- TBOOLEAN is_log; /* is this axis in logscale? */
- double log_base_log; /* if so, the log of its base */
- char *what; /* what is the coord for? */
- char *axis; /* which axis is this for ("x" or "y")? */
- {
- if (is_log) {
- if (coord <= 0.0) {
- char errbuf[100]; /* place to write error message */
- (void) sprintf(errbuf, "%s has %s coord of %g; must be above 0 for log scale!",
- what, axis, coord);
- graph_error(errbuf);
- } else
- return (log(coord) / log_base_log);
- }
- return (coord);
- }
-
- /* And the functions to map from user 3D space to terminal coordinates */
- void map3d_xy(x, y, z, xt, yt)
- double x, y, z;
- unsigned int *xt, *yt;
- {
- int i, j;
- double v[4], res[4], /* Homogeneous coords. vectors. */
- w = trans_mat[3][3];
-
- v[0] = map_x3d(x); /* Normalize object space to -1..1 */
- v[1] = map_y3d(y);
- v[2] = map_z3d(z);
- v[3] = 1.0;
-
- for (i = 0; i < 2; i++) { /* Dont use the third axes (z). */
- res[i] = trans_mat[3][i]; /* Initiate it with the weight factor */
- for (j = 0; j < 3; j++)
- res[i] += v[j] * trans_mat[j][i];
- }
-
- for (i = 0; i < 3; i++)
- w += v[i] * trans_mat[i][3];
- if (w == 0)
- w = 1e-5;
-
- *xt = (unsigned int) ((res[0] * xscaler / w) + xmiddle);
- *yt = (unsigned int) ((res[1] * yscaler / w) + ymiddle);
- }
-
-
-
- /* And the functions to map from user 3D space to terminal z coordinate */
- int map3d_z(x, y, z)
- double x, y, z;
- {
- int i, zt;
- double v[4], res, /* Homogeneous coords. vectors. */
- w = trans_mat[3][3];
-
- v[0] = map_x3d(x); /* Normalize object space to -1..1 */
- v[1] = map_y3d(y);
- v[2] = map_z3d(z);
- v[3] = 1.0;
-
- res = trans_mat[3][2]; /* Initiate it with the weight factor. */
- for (i = 0; i < 3; i++)
- res += v[i] * trans_mat[i][2];
- if (w == 0)
- w = 1e-5;
- for (i = 0; i < 3; i++)
- w += v[i] * trans_mat[i][3];
- zt = ((int) (res * 16384 / w));
- return zt;
- }
-
- /* borders of plotting area */
- /* computed once on every call to do_plot */
- static void boundary3d(scaling, plots, count)
- TBOOLEAN scaling; /* TRUE if terminal is doing the scaling */
- struct surface_points *plots;
- int count;
- {
- register struct termentry *t = term;
- int ytlen, i;
-
- titlelin = 0;
-
- p_height = pointsize * t->v_tic;
- p_width = pointsize * t->h_tic;
- if (key_swidth >= 0)
- key_sample_width = key_swidth * (t->h_char) + pointsize * (t->h_tic);
- else
- key_sample_width = 0;
- key_entry_height = pointsize * (t->v_tic) * 1.25 * key_vert_factor;
- if (key_entry_height < (t->v_char)) {
- /* is this reasonable ? */
- key_entry_height = (t->v_char) * key_vert_factor;
- }
-
- /* count max_len key and number keys (plot-titles and contour labels) with len > 0 */
- max_ptitl_len = find_maxl_keys3d(plots, count, &ptitl_cnt);
- if ((ytlen = label_width(key_title, &ktitle_lines)) > max_ptitl_len)
- max_ptitl_len = ytlen;
- key_col_wth = (max_ptitl_len + 4) * (t->h_char) + key_sample_width;
-
- /* luecken@udel.edu modifications
- sizes the plot to take up more of available resolution */
- if (lmargin >= 0)
- xleft = (t->h_char) * lmargin;
- else
- xleft = (t->h_char) * 2 + (t->h_tic);
- xright = (scaling ? 1 : xsize) * (t->xmax) - (t->h_char) * 2 - (t->h_tic);
- key_rows = ptitl_cnt;
- key_cols = 1;
- if (key == -1 && key_vpos == TUNDER) {
- if (ptitl_cnt > 0) {
- /* calculate max no cols, limited by label-length */
- key_cols = (int) (xright - xleft) / ((max_ptitl_len + 4) * (t->h_char) + key_sample_width);
- /* HBB 991019: fix division by zero problem */
- if (key_cols == 0)
- key_cols = 1;
- key_rows = (int) (ptitl_cnt / key_cols) + ((ptitl_cnt % key_cols) > 0);
- /* now calculate actual no cols depending on no rows */
- key_cols = (int) (ptitl_cnt / key_rows) + ((ptitl_cnt % key_rows) > 0);
- key_col_wth = (int) (xright - xleft) / key_cols;
- /* key_rows += ktitle_lines; - messes up key - div */
- } else {
- key_rows = key_cols = key_col_wth = 0;
- }
- }
- /* this should also consider the view and number of lines in
- * xformat || yformat || xlabel || ylabel */
-
- /* an absolute 1, with no terminal-dependent scaling ? */
- ybot = (t->v_char) * 2.5 + 1;
- if (key_rows && key_vpos == TUNDER)
- ybot += key_rows * key_entry_height + ktitle_lines * t->v_char;
-
- if (strlen(title.text)) {
- titlelin++;
- for (i = 0; i < strlen(title.text); i++) {
- if (title.text[i] == '\\')
- titlelin++;
- }
- }
- ytop = (scaling ? 1 : ysize) * (t->ymax) - (t->v_char) * (titlelin + 1.5) - 1;
- if (key == -1 && key_vpos != TUNDER) {
- /* calculate max no rows, limited be ytop-ybot */
- i = (int) (ytop - ybot) / (t->v_char) - 1 - ktitle_lines;
- if (ptitl_cnt > i) {
- key_cols = (int) (ptitl_cnt / i) + ((ptitl_cnt % i) > 0);
- /* now calculate actual no rows depending on no cols */
- key_rows = (int) (ptitl_cnt / key_cols) + ((ptitl_cnt % key_cols) > 0);
- }
- key_rows += ktitle_lines;
- }
- if (key_hpos == TOUT) {
- xright -= key_col_wth * (key_cols - 1) + key_col_wth - 2 * (t->h_char);
- }
- xleft += t->xmax * xoffset;
- xright += t->xmax * xoffset;
- ytop += t->ymax * yoffset;
- ybot += t->ymax * yoffset;
- xmiddle = (xright + xleft) / 2;
- ymiddle = (ytop + ybot) / 2;
- /* HBB 980308: sigh... another 16bit glitch: on term's with more than
- * 8000 pixels in either direction, these calculations produce garbage
- * results if done in (16bit) ints */
- xscaler = ((xright - xleft) * 4L) / 7L; /* HBB: Magic number alert! */
- yscaler = ((ytop - ybot) * 4L) / 7L;
-
- }
-
- #if 0
- /* not used ; anyway, should be done using bitshifts and squares,
- * rather than iteratively
- */
- static double dbl_raise(x, y)
- double x;
- int y;
- {
- register int i = ABS(y);
- double val = 1.0;
- while (--i >= 0)
- val *= x;
- if (y < 0)
- return (1.0 / val);
- return (val);
- }
- #endif
-
- /* we precalculate features of the key, to save lots of nested
- * ifs in code - x,y = user supplied or computed position of key
- * taken to be inner edge of a line sample
- */
- static int key_sample_left; /* offset from x for left of line sample */
- static int key_sample_right; /* offset from x for right of line sample */
- static int key_point_offset; /* offset from x for point sample */
- static int key_text_left; /* offset from x for left-justified text */
- static int key_text_right; /* offset from x for right-justified text */
- static int key_size_left; /* distance from x to left edge of box */
- static int key_size_right; /* distance from x to right edge of box */
-
- void do_3dplot(plots, pcount)
- struct surface_points *plots;
- int pcount; /* count of plots in linked list */
- {
- struct termentry *t = term;
- int surface;
- struct surface_points *this_plot = NULL;
- unsigned int xl, yl;
- int linetypeOffset = 0;
- /* double ztemp, temp; unused */
- struct text_label *this_label;
- struct arrow_def *this_arrow;
- TBOOLEAN scaling;
- transform_matrix mat;
- int key_count;
- char *s, *e;
-
- /* Initiate transformation matrix using the global view variables. */
- mat_rot_z(surface_rot_z, trans_mat);
- mat_rot_x(surface_rot_x, mat);
- mat_mult(trans_mat, trans_mat, mat);
- mat_scale(surface_scale / 2.0, surface_scale / 2.0, surface_scale / 2.0, mat);
- mat_mult(trans_mat, trans_mat, mat);
-
- #if 0
- /* HBB 19990609: this is *not* the way to implement 'set view' <z_scale> */
- /* modify min_z/max_z so it will zscale properly. */
- ztemp = (z_max3d - z_min3d) / (2.0 * surface_zscale);
- temp = (z_max3d + z_min3d) / 2.0;
- z_min3d = temp - ztemp;
- z_max3d = temp + ztemp;
- #endif /* 0 */
-
- /* The extrema need to be set even when a surface is not being
- * drawn. Without this, gnuplot used to assume that the X and
- * Y axis started at zero. -RKC
- */
-
- if (polar)
- graph_error("Cannot splot in polar coordinate system.");
-
- /* done in plot3d.c
- * if (z_min3d == VERYLARGE || z_max3d == -VERYLARGE ||
- * x_min3d == VERYLARGE || x_max3d == -VERYLARGE ||
- * y_min3d == VERYLARGE || y_max3d == -VERYLARGE)
- * graph_error("all points undefined!");
- */
-
- /* If we are to draw the bottom grid make sure zmin is updated properly. */
- if (xtics || ytics || work_grid.l_type) {
- base_z = z_min3d - (z_max3d - z_min3d) * ticslevel;
- if (ticslevel >= 0)
- floor_z = base_z;
- else
- floor_z = z_min3d;
-
- if (ticslevel < -1)
- ceiling_z = base_z;
- else
- ceiling_z = z_max3d;
- } else {
- floor_z = base_z = z_min3d;
- ceiling_z = z_max3d;
- }
-
- /* see comment accompanying similar tests of x_min/x_max and y_min/y_max
- * in graphics.c:do_plot(), for history/rationale of these tests */
- if (x_min3d == x_max3d)
- graph_error("x_min3d should not equal x_max3d!");
- if (y_min3d == y_max3d)
- graph_error("y_min3d should not equal y_max3d!");
- if (z_min3d == z_max3d)
- graph_error("z_min3d should not equal z_max3d!");
-
- #ifndef LITE
- if (hidden3d) {
- struct surface_points *plot;
- int p = 0;
- /* Verify data is hidden line removable - grid based. */
- for (plot = plots; ++p <= pcount; plot = plot->next_sp) {
- if (plot->plot_type == DATA3D && !plot->has_grid_topology) {
- fprintf(stderr, "Notice: Cannot remove hidden lines from non grid data\n");
- return;
- }
- }
- }
- #endif /* not LITE */
-
- term_start_plot();
-
- screen_ok = FALSE;
- scaling = (*t->scale) (xsize, ysize);
-
- /* now compute boundary for plot (xleft, xright, ytop, ybot) */
- boundary3d(scaling, plots, pcount);
-
- /* SCALE FACTORS */
- zscale3d = 2.0 / (ceiling_z - floor_z) * surface_zscale;
- yscale3d = 2.0 / (y_max3d - y_min3d);
- xscale3d = 2.0 / (x_max3d - x_min3d);
-
- term_apply_lp_properties(&border_lp); /* border linetype */
-
- /* PLACE TITLE */
- if (*title.text != 0) {
- write_multiline((unsigned int) ((xleft + xright) / 2 + title.xoffset * t->h_char),
- (unsigned int) (ytop + (titlelin + title.yoffset) * (t->h_char)),
- title.text, CENTRE, JUST_TOP, 0, title.font);
- }
- /* PLACE TIMEDATE */
- if (*timelabel.text) {
- char str[MAX_LINE_LEN+1];
- time_t now;
- unsigned int x = t->v_char + timelabel.xoffset * t->h_char;
- unsigned int y = timelabel_bottom ?
- yoffset * ymax + (timelabel.yoffset + 1) * t->v_char :
- ytop + (timelabel.yoffset - 1) * t->v_char;
-
- time(&now);
- strftime(str, MAX_LINE_LEN, timelabel.text, localtime(&now));
-
- if (timelabel_rotate && (*t->text_angle) (1)) {
- if (timelabel_bottom)
- write_multiline(x, y, str, LEFT, JUST_TOP, 1, timelabel.font);
- else
- write_multiline(x, y, str, RIGHT, JUST_TOP, 1, timelabel.font);
-
- (*t->text_angle) (0);
- } else {
- if (timelabel_bottom)
- write_multiline(x, y, str, LEFT, JUST_BOT, 0, timelabel.font);
- else
- write_multiline(x, y, str, LEFT, JUST_TOP, 0, timelabel.font);
- }
- }
- /* PLACE LABELS */
- for (this_label = first_label; this_label != NULL;
- this_label = this_label->next) {
- unsigned int x, y;
-
-
- map_position(&this_label->place, &x, &y, "label");
- if (this_label->rotate && (*t->text_angle) (1)) {
- write_multiline(x, y, this_label->text, this_label->pos, CENTRE, 1, this_label->font);
- (*t->text_angle) (0);
- } else {
- write_multiline(x, y, this_label->text, this_label->pos, CENTRE, 0, this_label->font);
- }
- }
-
- /* PLACE ARROWS */
- for (this_arrow = first_arrow; this_arrow != NULL;
- this_arrow = this_arrow->next) {
- unsigned int sx, sy, ex, ey;
-
- map_position(&this_arrow->start, &sx, &sy, "arrow");
- map_position(&this_arrow->end, &ex, &ey, "arrow");
- term_apply_lp_properties(&(this_arrow->lp_properties));
- (*t->arrow) (sx, sy, ex, ey, this_arrow->head);
- }
-
- #ifndef LITE
- if (hidden3d && draw_surface) {
- init_hidden_line_removal();
- reset_hidden_line_removal();
- hidden_active = TRUE;
- }
- #endif /* not LITE */
-
- /* WORK OUT KEY SETTINGS AND DO KEY TITLE / BOX */
-
- if (key_reverse) {
- key_sample_left = -key_sample_width;
- key_sample_right = 0;
- key_text_left = t->h_char;
- key_text_right = (t->h_char) * (max_ptitl_len + 1);
- key_size_right = (t->h_char) * (max_ptitl_len + 2 + key_width_fix);
- key_size_left = (t->h_char) + key_sample_width;
- } else {
- key_sample_left = 0;
- key_sample_right = key_sample_width;
- key_text_left = -(int) ((t->h_char) * (max_ptitl_len + 1));
- key_text_right = -(int) (t->h_char);
- key_size_left = (t->h_char) * (max_ptitl_len + 2 + key_width_fix);
- key_size_right = (t->h_char) + key_sample_width;
- }
- key_point_offset = (key_sample_left + key_sample_right) / 2;
-
- if (key == -1) {
- if (key_vpos == TUNDER) {
- #if 0
- yl = yoffset * t->ymax + (key_rows) * key_entry_height + (ktitle_lines + 2) * t->v_char;
- xl = max_ptitl_len * 1000 / (key_sample_width / (t->h_char) + max_ptitl_len + 2);
- xl *= (xright - xleft) / key_cols;
- xl /= 1000;
- xl += xleft;
- #else
- /* HBB 19990608: why calculate these again? boundary3d has already
- * done it... */
- if (ptitl_cnt > 0) {
- /* maximise no cols, limited by label-length */
- key_cols = (int) (xright - xleft) / key_col_wth;
- key_rows = (int) (ptitl_cnt + key_cols - 1) / key_cols;
- /* now calculate actual no cols depending on no rows */
- key_cols = (int) (ptitl_cnt + key_rows - 1) / key_rows;
- key_col_wth = (int) (xright - xleft) / key_cols;
- /* we divide into columns, then centre in column by considering
- * ratio of key_left_size to key_right_size
- * key_size_left/(key_size_left+key_size_right) * (xright-xleft)/key_cols
- * do one integer division to maximise accuracy (hope we dont
- * overflow !)
- */
- xl = xleft + ((xright - xleft) * key_size_left) / (key_cols * (key_size_left + key_size_right));
- yl = yoffset * t->ymax + (key_rows) * key_entry_height + (ktitle_lines + 2) * t->v_char;
- }
- #endif
- } else {
- if (key_vpos == TTOP) {
- yl = ytop - (t->v_tic) - t->v_char;
- } else {
- yl = ybot + (t->v_tic) + key_entry_height * key_rows + ktitle_lines * t->v_char;
- }
- if (key_hpos == TOUT) {
- /* keys outside plot border (right) */
- xl = xright + (t->h_tic) + key_size_left;
- } else if (key_hpos == TLEFT) {
- xl = xleft + (t->h_tic) + key_size_left;
- } else {
- xl = xright - key_size_right - key_col_wth * (key_cols - 1);
- }
- }
- yl_ref = yl - ktitle_lines * (t->v_char);
- }
- if (key == 1) {
- map_position(&key_user_pos, &xl, &yl, "key");
- }
- if (key && key_box.l_type > -3) {
- int yt = yl;
- int yb = yl - key_entry_height * (key_rows - ktitle_lines) - ktitle_lines * t->v_char;
- int key_xr = xl + key_col_wth * (key_cols - 1) + key_size_right;
- /* key_rows seems to contain title at this point ??? */
- term_apply_lp_properties(&key_box);
- (*t->move) (xl - key_size_left, yb);
- (*t->vector) (xl - key_size_left, yt);
- (*t->vector) (key_xr, yt);
- (*t->vector) (key_xr, yb);
- (*t->vector) (xl - key_size_left, yb);
-
- /* draw a horizontal line between key title and first entry JFi */
- (*t->move) (xl - key_size_left, yt - (ktitle_lines) * t->v_char);
- (*t->vector) (xl + key_size_right, yt - (ktitle_lines) * t->v_char);
- }
- /* DRAW SURFACES AND CONTOURS */
-
- #ifndef LITE
- if (hidden3d && draw_surface)
- plot3d_hidden(plots, pcount);
- #endif /* not LITE */
-
- /* KEY TITLE */
- if (key != 0 && strlen(key_title)) {
- char *ss = gp_alloc(strlen(key_title) + 2, "tmp string ss");
- strcpy(ss, key_title);
- strcat(ss, "\n");
- s = ss;
- yl -= t->v_char / 2;
- while ((e = (char *) strchr(s, '\n')) != NULL) {
- *e = '\0';
- if (key_just == JLEFT) {
- (*t->justify_text) (LEFT);
- (*t->put_text) (xl + key_text_left, yl, s);
- } else {
- if ((*t->justify_text) (RIGHT)) {
- (*t->put_text) (xl + key_text_right,
- yl, s);
- } else {
- int x = xl + key_text_right - (t->h_char) * strlen(s);
- if (inrange(x, xleft, xright))
- (*t->put_text) (x, yl, s);
- }
- }
- s = ++e;
- yl -= t->v_char;
- }
- yl += t->v_char / 2;
- free(ss);
- }
- key_count = 0;
- yl_ref = yl -= key_entry_height / 2; /* centralise the keys */
-
- #define NEXT_KEY_LINE() \
- if ( ++key_count >= key_rows ) { \
- yl = yl_ref; xl += key_col_wth; key_count = 0; \
- } else \
- yl -= key_entry_height
-
- this_plot = plots;
- for (surface = 0;
- surface < pcount;
- this_plot = this_plot->next_sp, surface++) {
-
- #ifndef LITE
- if (hidden3d)
- hidden_no_update = FALSE;
- #endif /* not LITE */
-
- if (draw_surface) {
- int lkey = (key != 0 && this_plot->title && this_plot->title[0]);
- term_apply_lp_properties(&(this_plot->lp_properties));
-
- #ifndef LITE
- if (hidden3d) {
- hidden_line_type_above = this_plot->lp_properties.l_type;
- hidden_line_type_below = this_plot->lp_properties.l_type + 1;
- }
- #endif /* not LITE */
-
- if (lkey) {
- key_text(xl, yl, this_plot->title);
- }
- switch (this_plot->plot_style) {
- case BOXES: /* can't do boxes in 3d yet so use impulses */
- case IMPULSES:{
- if (lkey) {
- key_sample_line(xl, yl);
- }
- if (!(hidden3d && draw_surface))
- plot3d_impulses(this_plot);
- break;
- }
- case STEPS: /* HBB: I think these should be here */
- case FSTEPS:
- case HISTEPS:
- case LINES:{
- if (lkey) {
- key_sample_line(xl, yl);
- }
- if (!(hidden3d && draw_surface))
- plot3d_lines(this_plot);
- break;
- }
- case YERRORBARS: /* ignored; treat like points */
- case XERRORBARS: /* ignored; treat like points */
- case XYERRORBARS: /* ignored; treat like points */
- case BOXXYERROR: /* HBB: ignore these as well */
- case BOXERROR:
- case CANDLESTICKS: /* HBB: dito */
- case FINANCEBARS:
- case VECTOR:
- case POINTSTYLE:
- if (lkey && !clip_point(xl + key_point_offset, yl)) {
- key_sample_point(xl, yl, this_plot->lp_properties.p_type);
- }
- if (!(hidden3d && draw_surface))
- plot3d_points(this_plot);
- break;
-
- case LINESPOINTS:
- /* put lines */
- if (lkey)
- key_sample_line(xl, yl);
-
- if (!(hidden3d && draw_surface))
- plot3d_lines(this_plot);
-
- /* put points */
- if (lkey && !clip_point(xl + key_point_offset, yl))
- key_sample_point(xl, yl, this_plot->lp_properties.p_type);
-
- if (!(hidden3d && draw_surface))
- plot3d_points(this_plot);
-
- break;
-
- case DOTS:
- if (lkey) {
- if (key == 1) {
- if (!clip_point(xl + key_point_offset, yl))
- (*t->point) (xl + key_point_offset, yl, -1);
- } else {
- (*t->point) (xl + key_point_offset, yl, -1);
- /* (*t->point)(xl+2*(t->h_char),yl, -1); */
- }
- }
- if (!(hidden3d && draw_surface))
- plot3d_dots(this_plot);
-
- break;
-
-
- } /* switch(plot-style) */
-
- /* move key on a line */
- if (lkey) {
- NEXT_KEY_LINE();
- }
- } /* draw_surface */
-
- #ifndef LITE
- if (hidden3d) {
- hidden_no_update = TRUE;
- hidden_line_type_above = this_plot->lp_properties.l_type + (hidden3d ? 2 : 1);
- hidden_line_type_below = this_plot->lp_properties.l_type + (hidden3d ? 2 : 1);
- }
- #endif /* not LITE */
-
- if (draw_contour && this_plot->contours != NULL) {
- struct gnuplot_contours *cntrs = this_plot->contours;
-
- term_apply_lp_properties(&(this_plot->lp_properties));
- (*t->linetype) (this_plot->lp_properties.l_type + (hidden3d ? 2 : 1));
-
- if (key != 0 && this_plot->title && this_plot->title[0]
- && !draw_surface && !label_contours) {
- /* unlabelled contours but no surface : put key entry in now */
- key_text(xl, yl, this_plot->title);
-
- switch (this_plot->plot_style) {
- case IMPULSES:
- case LINES:
- case BOXES: /* HBB: I think these should be here... */
- case STEPS:
- case FSTEPS:
- case HISTEPS:
- key_sample_line(xl, yl);
- break;
- case YERRORBARS: /* ignored; treat like points */
- case XERRORBARS: /* ignored; treat like points */
- case XYERRORBARS: /* ignored; treat like points */
- case BOXERROR: /* HBB: ignore these as well */
- case BOXXYERROR:
- case CANDLESTICKS: /* HBB: dito */
- case FINANCEBARS:
- case VECTOR:
- case POINTSTYLE:
- key_sample_point(xl, yl, this_plot->lp_properties.p_type);
- break;
- case LINESPOINTS:
- key_sample_line(xl, yl);
- break;
- case DOTS:
- key_sample_point(xl, yl, -1);
- break;
- }
- NEXT_KEY_LINE();
- }
- linetypeOffset = this_plot->lp_properties.l_type + (hidden3d ? 2 : 1);
- while (cntrs) {
- if (label_contours && cntrs->isNewLevel) {
- (*t->linetype) (linetypeOffset++);
- if (key) {
-
- #ifndef LITE
- if (hidden3d)
- hidden_line_type_below = hidden_line_type_above = linetypeOffset - 1;
- #endif /* not LITE */
-
- key_text(xl, yl, cntrs->label);
-
- switch (this_plot->plot_style) {
- case IMPULSES:
- case LINES:
- case LINESPOINTS:
- case BOXES: /* HBB: these should be treated as well... */
- case STEPS:
- case FSTEPS:
- case HISTEPS:
- key_sample_line(xl, yl);
- break;
- case YERRORBARS: /* ignored; treat like points */
- case XERRORBARS: /* ignored; treat like points */
- case XYERRORBARS: /* ignored; treat like points */
- case BOXERROR: /* HBB: treat these likewise */
- case BOXXYERROR:
- case CANDLESTICKS: /* HBB: dito */
- case FINANCEBARS:
- case VECTOR:
- case POINTSTYLE:
- key_sample_point(xl, yl, this_plot->lp_properties.p_type);
- break;
- case DOTS:
- key_sample_point(xl, yl, -1);
- break;
- } /* switch */
-
- NEXT_KEY_LINE();
-
- } /* key */
- } /* label_contours */
- /* now draw the contour */
- switch (this_plot->plot_style) {
- case IMPULSES:
- case BOXES: /* HBB: this should also be treated somehow */
- cntr3d_impulses(cntrs, this_plot);
- break;
- case LINES:
- case STEPS: /* HBB: these should also be handled, I think */
- case FSTEPS:
- case HISTEPS:
- cntr3d_lines(cntrs);
- break;
- case YERRORBARS: /* ignored; treat like points */
- case XERRORBARS: /* ignored; treat like points */
- case XYERRORBARS: /* ignored; treat like points */
- case BOXERROR: /* HBB: ignore these too... */
- case BOXXYERROR:
- case CANDLESTICKS: /* HBB: dito */
- case FINANCEBARS:
- case VECTOR:
- case POINTSTYLE:
- cntr3d_points(cntrs, this_plot);
- break;
- case LINESPOINTS:
- cntr3d_lines(cntrs);
- cntr3d_points(cntrs, this_plot);
- break;
- case DOTS:
- cntr3d_dots(cntrs);
- break;
- } /*switch */
-
- cntrs = cntrs->next;
- } /* loop over contours */
- } /* draw contours */
- } /* loop over surfaces */
-
- draw_bottom_grid(plots, pcount);
-
- term_end_plot();
-
- #ifndef LITE
- if (hidden3d && draw_surface) {
- term_hidden_line_removal();
- hidden_active = FALSE;
- }
- #endif /* not LITE */
-
- }
-
- /* plot3d_impulses:
- * Plot the surfaces in IMPULSES style
- */
- static void plot3d_impulses(plot)
- struct surface_points *plot;
- {
- int i; /* point index */
- unsigned int x, y, x0, y0; /* point in terminal coordinates */
- struct iso_curve *icrvs = plot->iso_crvs;
-
- while (icrvs) {
- struct coordinate GPHUGE *points = icrvs->points;
-
- for (i = 0; i < icrvs->p_count; i++) {0h